home *** CD-ROM | disk | FTP | other *** search
- /*
- SetPriority.c
-
- SetPriority(1);
- // do high priority stuff here
- SetPriority(0);
-
- Get and set the processor priority. The Macintosh operating system
- normally leaves the processor priority at zero, allowing all interrupts.
- You can temporarily block interrupts by raising the processor priority.
- The highest level is 7, blocking all interrupts. This is useful for time
- critical tasks, such as running video animations, where your primary
- concern is video timing, and you're willing to miss AppleTalk and
- keyboard events. Note that while the processor priority is high the
- keyboard and mouse will be dead, so that it is essential that your
- program lower it back down to allow the user to regain control.
-
- Note that it may be enough to raise priority from the normal 0 to 1,
- because that blocks all deferred tasks until you take priority back down
- to 0. See the Deferred Task Manager in the Inside Mac Processes book.
-
- It's a strange fact, but interrupt priority on PPC Macs is controlled
- by the processor priority of the emulated 68K processor. And the only
- way to set or get the processor priority is to run (possibly emulated)
- 68K code that accesses the 68K Status Register, as we do here using the
- inline functions GetStatusRegister() and SetStatusRegister().
-
- Apple's Technote 1001 explains that processor priority is not hardware
- implemented in the PowerPC and that in fact there is no legal way to set
- it from PPC code. The suggested work-around, for old code, is to call a
- bit of 68K code since the 68K emulator will then do the right thing,
- setting the effective priority. That's what we do here. When compiled as
- PowerPC code the function calls a 68K version of the routines to actual
- get and set the priority. Technote 1094 (on VM) gives some details about
- emulation of the priviledged 68K instructions that access the SR.
-
- SetPriority and GetPriority are trivial and fast when compiled as 68K
- code. They incur the cost of a mixed-mode switch (to and fro) when
- run as PPC code, because the actual set/get of priority can only be done
- as 68K code. I think the mixed mode switch takes on the order of 100
- microseconds, but that's only a vague recollection.
-
- SEE:
- http://devworld.apple.com/dev/technotes/tn/tn1001.html
- <http://devworld.apple.com/dev/technotes/tn/tn1094.html>
- http://devworld.apple.com/dev/techsupport/insidemac/PPCSoftware/PPCSoftware-14.html
-
- ACKNOWLEDGEMENTS:
- Thanks for help from:
- Quinn "The Eskimo!" <http://devworld.apple.com/dev/geeks.html> 421080
- Bo3b Johnson, Apple Developer Technical Support 421080
-
- HISTORY:
- 1989? dgp wrote it
- 8/1/91 dgp introduced the inline functions as a way to isolate the machine code
- part, and to make it compatible with MPW C as well as THINK C.
- 8/6/91 dgp fixed definition of GetStatusRegister() to make it a legal prototype.
- 2/15/93 dgp added SwapPriority().
- 7/29/94 dgp disable all code if compiling for PowerPC
- 4/13/97 dgp Made callable from PowerPC code.
- 4/15/97 dgp Mention deferred tasks.
- 4/17/97 dgp MakeDataExecutable
- 4/28/97 dgp Deleted an erronous comment above about User/Supervisor mode.
- */
- #include "VideoToolbox.h"
-
- #if GENERATING68K
- /* 68k inline functions supported by THINK, MPW, and CodeWarrior C. */
- pascal short GetStatusRegister(void)=0x40d7; /* MOVE.W SR,(SP) */
- pascal void SetStatusRegister(short status)=0x46df; /* MOVE.W (SP)+,SR */
- #else
- #include <OSUtils.h> // FlushCodeCacheRange
- /* 68K code, as compiled by CodeWarrior C. */
- short SetPriority68K[]=
- {0x48E7,0x1800,0x282F,0x000C,0x7007,0xC880,0xE18C,0x554F
- ,0x40D7,0x301F,0x3600,0x0243,0xF8FF,0x8644,0x3F03,0x46DF,0x4CDF
- ,0x0018,0x4E74,0x0004,0x8B53,0x4554,0x5052,0x494F,0x5249,0x5459,0x0000};
- short GetPriority68K[]=
- {0x2F03,0x7600,0x554F,0x40D7,0x301F,0x3600,0xE043
- ,0x0243,0x0007,0x3003,0x48C0,0x2F40,0x0008,0x261F
- ,0x4E75,0x8B47,0x4554,0x5052,0x494F,0x5249,0x5459,0x0000};
- enum {
- setPriority68KProcInfo = kPascalStackBased | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
- ,getPriority68KProcInfo = kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(long)))
- };
- #endif
-
- pascal void SetPriority(long i)
- {
- #if GENERATING68K
- register short status;
-
- i &= 7;
- i <<= 8;
- status=GetStatusRegister();
- status &= ~0x700; // clear the priority bits
- status |= i; // insert new priority bits
- SetStatusRegister(status);
- #else
- static Boolean firstTime=1;
- if(firstTime){
- MakeDataExecutable(SetPriority68K,sizeof(SetPriority68K));
- firstTime=0;
- }
- CallUniversalProc((UniversalProcPtr)SetPriority68K,setPriority68KProcInfo,i);
- #endif
- }
-
- pascal long GetPriority(void)
- {
- register short status=0;
-
- #if GENERATING68K
- status=GetStatusRegister();
- status >>= 8;
- status &= 7;
- #else
- static Boolean firstTime=1;
- if(firstTime){
- MakeDataExecutable(GetPriority68K,sizeof(GetPriority68K));
- firstTime=0;
- }
- status=CallUniversalProc((UniversalProcPtr)GetPriority68K,getPriority68KProcInfo);
- #endif
- return status;
- }
-
- void SwapPriority(char *priority)
- {
- char oldPriority;
-
- oldPriority=GetPriority();
- SetPriority(*priority);
- *priority=oldPriority;
- }
-
- /*
- Compiled without A6 Stack frames (linker option) because the Linker won't get to
- fix up the zero field left by the compiler.
-
- Hunk: Kind=HUNK_GLOBAL_CODE Name="SETPRIORITY"(1) Size=54
- 00000000: 48E7 1800 MOVEM.L D3/D4,-(A7)
- 00000004: 282F 000C MOVE.L $000C(A7),D4
- 00000008: 7007 MOVEQ #$07,D0
- 0000000A: C880 AND.L D0,D4
- 0000000C: E18C LSL.L #$8,D4
- 0000000E: 554F SUBQ.W #$2,A7
- 00000010: 40D7 MOVE SR,(A7)
- 00000012: 301F MOVE.W (A7)+,D0
- 00000014: 3600 MOVE.W D0,D3
- 00000016: 0243 F8FF ANDI.W #$F8FF,D3
- 0000001A: 8644 OR.W D4,D3
- 0000001C: 3F03 MOVE.W D3,-(A7)
- 0000001E: 46DF MOVE (A7)+,SR
- 00000020: 4CDF 0018 MOVEM.L (A7)+,D3/D4
- 00000024: 4E74 0004 RTD #$0004
- 00000028: 8B53 4554 5052 DC.B $80+$0B, 'SETPRIORITY'
- 494F 5249 5459
- 00000034: 0000
-
- Hunk: Kind=HUNK_GLOBAL_CODE Name="GETPRIORITY"(2) Size=44
- 00000000: 2F03 MOVE.L D3,-(A7)
- 00000002: 7600 MOVEQ #$00,D3
- 00000004: 554F SUBQ.W #$2,A7
- 00000006: 40D7 MOVE SR,(A7)
- 00000008: 301F MOVE.W (A7)+,D0
- 0000000A: 3600 MOVE.W D0,D3
- 0000000C: E043 ASR.W #$8,D3
- 0000000E: 0243 0007 ANDI.W #$0007,D3
- 00000012: 3003 MOVE.W D3,D0
- 00000014: 48C0 EXT.L D0
- 00000016: 2F40 0008 MOVE.L D0,$0008(A7)
- 0000001A: 261F MOVE.L (A7)+,D3
- 0000001C: 4E75 RTS
- 0000001E: 8B47 4554 5052 DC.B $80+$0B, 'GETPRIORITY'
- 494F 5249 5459
- 0000002A: 0000
- */
-